<?php

/**
 * \file
 * Classe `Field`.
 */
 
namespace pilar\Objects /* \cond */ ; /* \endcond */
{

/**
 * Champ d'un objet d'une entité abstraite.
 *
 * \since 07/10/2008
 * \author Matthieu OVIEDO <matthieu.oviedo@gmail.com>
 */
class Field {

/**
 * Membre parent.
 *
 * \since 07/10/2008
 */
private $_parentMember;


/**
 * Champ d'entité type du champ.
 *
 * \since 07/10/2008
 */
private $_entityField;


/**
 * Valeur en base de données du champ.
 *
 * \since 07/10/2008
 */
private $_dbValue;


/**
 * Valeur courante du champ.
 *
 * \since 07/10/2008
 */
private $_value;


/**
 * Constructeur.
 *
 * \since 07/10/2008
 * \param $entityField Champ d'entité type du champ.
 */
public function __construct($entityField) {
 $this->_parentMember = null;
 $this->_entityField = $entityField;
 $this->_dbValue = null;
 $this->_value = $entityField->computeDefaultValue();
}


/**
 * Permet de spécifier le membre parent du champ.
 *
 * \since 07/10/2008
 * \param $member Membre parent.
 */
public function setParentMember($member) {
 $this->_parentMember = $member;
}


/**
 * Valeur courante champ.
 *
 * \since 07/10/2008
 * \return Valeur du champ.
 */
public function get() {
 return $this->_value;
}


/**
 * Change la valeur du champ.
 *
 * \since 07/10/2008
 * \param $value Nouvelle valeur du champ.
 * \return Instance de l'objet parent.
 */
public function set($value) {
 $parentObject = $this->_parentMember->parentObject();

 // On s'assure que le champ ne soit pas protégé en écriture :
  if($this->_entityField->isProtected()) {
   trigger_error(
    "Le champ est protégé en écriture. Impossible de changer sa valeur.",
    E_USER_ERROR
   );
   return $parentObject;
  }
  
 // Si la valeur est la même que la valeur courante on sort :
  if($value == $this->_value) return $parentObject;
  
 // On s'assure que la valeur soit acceptable :
  if(!$this->_entityField->acceptsValue($value)) {
   trigger_error(
    "Le champ `".$this->_entityField->get('name')."` n'accepte pas la valeur `{$value}`.",
    E_USER_ERROR
   );
   return $parentObject;
  }
  
 // Formatage de la valeur :
  $formatValue = $this->_entityField->formatValue($value);
 
 // Si la valeur est la même que la valeur courante on sort :
  if($formatValue == $this->_value) return $parentObject;
  
 // A ce stade la valeur est correcte, formattée, et connue comme différente
 // de la valeur courante.
 
 // Mise à jour de la valeur locale :
  $this->_value = $formatValue;

 // Mise à niveau de tous les membres influencés :
  foreach($this->_parentMember->entityMember()->succeedingMembers()
          as $name => $entityMember) {
   $entityMember->upgradeObject(
    $parentObject,
    $parentObject->__get(
     $entityMember->get('name')
    )
   );
  }
 
 return $parentObject;
}


/**
 * Description DOM du champ.
 *
 * \param $domDoc \DOMDocument a utiliser comme document parent.
 * \return Noeud DOM de la description du champ.
 *
 * \since 07/10/2008
 */
public function domNode_meta($domDoc) {
 $domField = $domDoc->createElement('field');
 
 $domField->setAttribute('name', $this->_entityField->get('name'));
 
 $domField->appendChild($domDoc->createTextNode($this->_value));

 return $domField;
}


/**
 * Version DOM du champ.
 *
 * \param $domDoc \DOMDocument a utiliser comme document parent.
 * \return Attribut DOM du champ.
 *
 * \since 10/12/2008
 */
public function domNode($domDoc) {
 $domField = $domDoc->createAttribute($this->_entityField->get('name'));

 $domField->appendChild($domDoc->createTextNode($this->_value));

 return $domField;
}


/**
 * Version DOM 'générique' du champ.
 *
 * \param $domDoc \DOMDocument a utiliser comme document parent.
 * \return Attribut DOM générique du champ.
 * \since 03/03/2009
 */
/*public function domNode_generic($domDoc) {
	$domField = $domDoc->createElement
}*/


/**
 * Flush le champ.
 *
 * \since 07/10/2008
 */
public function flush() {
 $this->_dbValue = $this->_value;
}


/**
 * Remet à zéro le champ.
 *
 * \since 07/10/2008
 */
public function reset() {
 $this->_dbValue = null;
 $this->_value = $this->_entityField->computeDefaultValue();
}


/**
 * Permet de synchroniser le champ avec sa valeur en base de données.
 *
 * \since 07/10/2008
 */
public function sync($value) {
 $this->_dbValue = $this->_value = $value;
}


/**
 * Détermine si le champ a été modifié.
 *
 * \since 07/10/2008
 */
public function changed() {
 return ($this->_value != null && $this->_value != $this->_dbValue);
}


/**
 * Code SQL d'assignation pour les commandes UPDATE.
 *
 * \since 07/10/2008
 * \return Code d'assignation.
 */
public function assignSqlCode() {
 return '`'.$this->_entityField->fullName().'` = \''.\db\escape($this->_value).'\'';
}


} // Class.

} // Namespace.

?>
